fix(memory): skip non-dict rows in extract_schema_items/describe - #2586
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThe schema indexer now normalizes malformed nested manifest fields, skips invalid entries during description and extraction, and filters model and cube summaries to valid named dictionary children. New tests cover malformed rows, scalar collections, and invalid top-level sections. ChangesSchema indexing safeguards
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/wren/src/wren/memory/schema_indexer.py`:
- Around line 53-63: Update the manifest collection handling in the function
containing the model, relationship, and view loops, plus the analogous columns
handling, to iterate only when each field is an actual list; otherwise use an
empty collection. Preserve the existing per-item dictionary guards and add
regression coverage for truthy scalar values such as numeric or mapping fields,
ensuring malformed collections do not raise TypeError.
- Around line 238-241: Update the column iteration in the schema indexing flow
to skip dictionary entries whose name is missing or empty before calling
_column_record. Reuse the same col.get("name") validation pattern as
_model_record, while preserving the existing non-dictionary skip behavior.
In `@core/wren/tests/unit/test_schema_indexer_extract_nonduct.py`:
- Around line 6-29: Strengthen
test_extract_skips_non_dict_models_columns_rels_views_without_raise by asserting
the exact extracted record count and validating each item’s type and identifying
name. Confirm malformed column, relationship, and view entries produce no
records while the valid orders model and its valid column remain included.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 0d89af41-8392-4861-a7ad-a6b409ff895e
📒 Files selected for processing (2)
core/wren/src/wren/memory/schema_indexer.pycore/wren/tests/unit/test_schema_indexer_extract_nonduct.py
|
Thanks @coderabbitai — good catches, all three addressed in the latest push:
All 3 tests pass; ruff format + check clean. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
core/wren/tests/unit/test_schema_indexer_extract_nonduct.py (1)
26-36: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winCover the remaining defensive branches.
These tests do not exercise dictionary columns with missing or empty
"name"values, nor truthy-scalarcubescollections. Add those cases so the new validation and_as_list()cube path cannot regress unnoticed.Also applies to: 39-47
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@core/wren/tests/unit/test_schema_indexer_extract_nonduct.py` around lines 26 - 36, Extend the schema extraction test around the existing valid-item assertions to include dictionary columns whose “name” is missing or empty, and verify those entries are discarded. Add a truthy scalar “cubes” value to exercise the _as_list() path, asserting it is handled without producing invalid items or errors.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@core/wren/tests/unit/test_schema_indexer_extract_nonduct.py`:
- Around line 26-36: Extend the schema extraction test around the existing
valid-item assertions to include dictionary columns whose “name” is missing or
empty, and verify those entries are discarded. Add a truthy scalar “cubes” value
to exercise the _as_list() path, asserting it is handled without producing
invalid items or errors.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 926b926c-e586-4a42-94f2-7131b06c8f87
📒 Files selected for processing (2)
core/wren/src/wren/memory/schema_indexer.pycore/wren/tests/unit/test_schema_indexer_extract_nonduct.py
🚧 Files skipped from review as they are similar to previous changes (1)
- core/wren/src/wren/memory/schema_indexer.py
|
Tip For best results, initiate chat on the files or code changes.
🐇✨ If you found this review helpful, would you consider giving us a shout-out on X? Thank you for using CodeRabbit! |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
git diff --check
git diff -- core/wren/src/wren/memory/schema_indexer.py core/wren/tests/unit/test_schema_indexer_extract_nonduct.py
ast-grep outline core/wren/src/wren/memory/schema_indexer.py --items all \
--match '_as_list|describe_schema|extract_schema_items|_model_record'
ast-grep outline core/wren/tests/unit/test_schema_indexer_extract_nonduct.py --items all
rg -n -A45 -B8 \
'def _as_list|def describe_schema|def extract_schema_items|def _model_record|def test_extract_skips_non_dict_models_columns_rels_views_without_raise|def test_describe_skips_non_dict_rows' \
core/wren/src/wren/memory/schema_indexer.py \
core/wren/tests/unit/test_schema_indexer_extract_nonduct.pyLength of output: 22577
🔥 Failed to add learningsLearnings cannot be added due to server error. Please try again. If you found this review helpful, would you consider giving us a shout-out on X? Thank you for using CodeRabbit! |
d1472b4 to
d051458
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/wren/tests/unit/test_schema_indexer_extract_nonduct.py`:
- Around line 64-72: Strengthen test_describe_skips_non_dict_rows by replacing
the malformed relationship and view values with unique sentinel strings, then
assert those sentinels are absent from the returned text while retaining the
assertion that the valid model name is included.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 0511e2b5-0954-4250-a0fd-3773a7bf82b0
📒 Files selected for processing (2)
core/wren/src/wren/memory/schema_indexer.pycore/wren/tests/unit/test_schema_indexer_extract_nonduct.py
🚧 Files skipped from review as they are similar to previous changes (1)
- core/wren/src/wren/memory/schema_indexer.py
|
I traced this one properly, and unlike some of the others in this batch the guards here are reachable — two ways:
So a truthy non-list nested collection is a real input, and the tests are the right shape too — they call One thing to settle before merge: this contradicts #2605 on policy. Your own
— but #2605 adds I'd rather have one rule. The argument for raising on both is that Could you and #2605 converge on one of those? Whichever you pick, |
|
Thanks @goldmedal — appreciate you tracing the reachability; agreed both paths ( On the policy split with #2605: I'll converge on raise, not silent-empty. Your argument is the right one — I'll update this PR so |
|
Pushed dc3ed2c with the converged policy:
Since both PRs touch |
|
Re-reviewed at e5e8a1b. Thanks for taking the raise route — that's the right call, and the tests now assert the policy per field name rather than just "doesn't crash". But the "one rule across the module" claim isn't true yet — falsy non-lists still diverge. if value is None or not value:
return []Compare the two helpers it says it matches, both of which special-case
So
One line fixes it: if value is None:
return []
The tests are why it slipped. Smaller things:
One behavioural note for the description/CHANGELOG: the new raise widens where Fix the |
4abdd80 to
3afd0a8
Compare
|
Pushed 3afd0a8 — you're right, the
Rebased onto your ruff-format tip (e5e8a1b). Couldn't run the suite locally ( |
|
Re-reviewed at 9d6ab81. Everything from the last round is addressed, and correctly:
CI is green across all ten checks. One thing left, and it's about the docstring's claim rather than the code. It says:
models = rel.get("models") or []So if this merges first, the module ends up with two rules, and the surviving one is the worse of the two: Either fix works:
I'd prefer (1) — it also means the Otherwise this is ready. |
|
#2605 is merged ( Good news on the docstring. Now the correction I owe you on the error message. Two rounds ago I asked you to match Having reviewed #2605 next to this, I got that backwards and I'd like you to reverse it. What's now in That names the offending entity, which is what someone editing their project actually needs. So the rule I'd like across the module:
Concretely, One edge case to decide while you're at it. Models are required to have a name, but cubes aren't — both The test matchers are currently anchored to Sorry for the round-trip on this one; the format only became obvious with both helpers side by side. |
Keep _iter_section raises for top-level wrong-type sections. Add _as_list for nested columns/measures/dimensions so truthy scalars cannot TypeError, plus unit coverage for non-dict rows and nested scalar collections.
Converge policy with Canner#2605 per review: a truthy non-list nested field (columns/measures/dimensions/timeDimensions) is a structural manifest error and now raises ValueError instead of silently emptying the index. None/missing/empty still pass through as []. The CLI already catches ValueError -> 'Malformed manifest'. Thread a field name for a clear message; update tests to assert raise + the passthrough case.
Address review: _as_list short-circuited on any falsy value, so
columns: {} / 0 / "" silently indexed zero columns — the exact
outcome the docstring says it raises to prevent. Change to only pass
None; every other non-list raises, matching _iter_section and Canner#2605's
_relationship_models (one rule across the module). Unify message to
manifest['field'] form, make field a required positional, drop brittle
len==4 assert, add falsy non-list test cases.
CI failed after raise-policy polish: ruff format wanted a wrapped ValueError, and unit matchers still expected the old short message.
Update _as_list to surface the parent entity in the raised ValueError instead of the top-level 'manifest["columns"]' format, aligning with the new Canner#2605 relationship implementation. Also replaces earlier tests with exact message assertions. Requested-by: goldmedal (Canner#2586)
9d6ab81 to
62bba94
Compare
|
Pushed 106b4d8 — rebased on current
ruff format + check clean, py-compiles clean. Couldn't run the suite locally ( Thanks for the side-by-side correction — the entity-named form is clearly the right call for a nested field. |
|
Re-reviewed at 106b4d8. Rebased onto the merged #2605 (the base blob is the post- Two things left, and the first one is a suggestion of mine that I now think was the wrong half of the choice I gave you. 1. The unnamed-cube fallback invents a manifest key that doesn't exist. I offered either
2. The matchers lost the type half. I asked for these to stay as tight as #2605's, and they're per-field but no longer per-type: with pytest.raises(ValueError, match=r"model 'm': 'columns' must be a list"):#2605 pins Everything else is settled as far as I'm concerned — the policy, the sweep, the falsy handling, the entity naming, the passthrough cases, and the extra |
|
Pushed ac1898d — both settled. 1. Unnamed cube no longer invents a top-level key. You're right — 2. Matchers are per-type again. Every case in ruff format + check clean, py-compiles clean. Couldn't run the suite locally ( |
Summary
extract_schema_itemsanddescribe_schemaskip non-dict models/columns/relationships/views.Motivation
MDL lists can contain non-object entries from hand-edited JSON;
.get/key access crashed indexing.Verification
core/wren/.venv/bin/python -m pytest tests/unit/test_schema_indexer_extract_nonduct.py -q— 2 passedLicense
Touches
core/**(Apache-2.0).Summary by CodeRabbit